package com.zhn.evsi.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhn.evsi.client.AssetsClient;
import com.zhn.evsi.client.ThirdClient;
import com.zhn.evsi.common.RedisCache;
import com.zhn.evsi.domain.dto.evsi.EvsiMarketStatDTO;
import com.zhn.evsi.domain.dto.evsi.assets.EvsiAssetListDTO;
import com.zhn.evsi.domain.dto.evsi.assets.EvsiAssetLocationDTO;
import com.zhn.evsi.domain.dto.evsi.assets.EvsiAssetNameDTO;
import com.zhn.evsi.domain.dto.evsi.character.EvsiCharacterPublicInfoDTO;
import com.zhn.evsi.domain.entity.evsi.EvsiAssets;
import com.zhn.evsi.domain.entity.evsi.EvsiInvtypes;
import com.zhn.evsi.domain.vo.EvsiAssetsOnMarketVO;
import com.zhn.evsi.exception.CustomException;
import com.zhn.evsi.interceptor.CharacterInterceptor;
import com.zhn.evsi.mapper.EvsiAssetsMapper;
import com.zhn.evsi.service.IEvsiAssetsService;
import com.zhn.evsi.service.IEvsiInvtypesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class EvsiAssetsServiceImpl extends ServiceImpl<EvsiAssetsMapper, EvsiAssets> implements IEvsiAssetsService {

    @Value("${eve.sellTax}")
    private Double sellTaxValue;

    @Value("${eve.buyTax}")
    private Double buyTaxValue;

    @Autowired
    private AssetsClient assetsClient;

    @Autowired
    private CharacterInterceptor characterInterceptor;

    @Resource
    private ThirdClient thirdClient;

    @Autowired
    private IEvsiInvtypesService invtypesService;

    /**
     * 查询资产
     * */
    @Override
    public List<EvsiAssetListDTO> assetList() {
        EvsiCharacterPublicInfoDTO characters = characterInterceptor.getCharacters(null);
        List<EvsiAssetListDTO> assetListDTOList = new ArrayList<>();
        for (int i=1; i<100; i++) {
            List<EvsiAssetListDTO> assetListDTOS = assetsClient.assetList(characters.getCharacters(), i);
            assetListDTOList.addAll(assetListDTOS);

            if (assetListDTOS.size() < 1000) {
                break;
            }
        }
        assetListDTOList.forEach(v -> v.setCharacters(characters.getCharacters()));
        return assetListDTOList;
    }

    /**
     * 资产所在地点
     * */
    @Override
    public List<EvsiAssetLocationDTO> assetLocations() {
        EvsiCharacterPublicInfoDTO characterPublicInfoDTO = characterInterceptor.getCharacters(null);
        List<BigInteger> itemIds = this.assetList().stream().map(EvsiAssetListDTO::getItem_id).collect(Collectors.toList());
        return assetsClient.assetLocations(characterPublicInfoDTO.getCharacters(), itemIds);
    }

    /**
     * 查询资产名称
     * */
    @Override
    public List<EvsiAssetNameDTO> assetNames() {
        EvsiCharacterPublicInfoDTO characterPublicInfoDTO = characterInterceptor.getCharacters(null);
        List<BigInteger> itemIds = this.assetList().stream().map(EvsiAssetListDTO::getItem_id).collect(Collectors.toList());
        return assetsClient.assetNames(characterPublicInfoDTO.getCharacters(), itemIds);
    }

    /**
     * 查询军团资产
     * */
    @Override
    public List<EvsiAssetListDTO> assetCorpList() {
        List<EvsiAssetListDTO> assetListDTOList = new ArrayList<>();
        EvsiCharacterPublicInfoDTO characters = characterInterceptor.getCharacters(null);
        for (int i=1; i<100; i++) {
            List<EvsiAssetListDTO> assetCorpListDTOS = assetsClient.assetCorpList(characters.getCorporation_id(), i);
            assetListDTOList.addAll(assetCorpListDTOS);
            if (assetCorpListDTOS.size() < 1000) {
                break;
            }
        }
        assetListDTOList.forEach(v -> v.setCorporations(characters.getCorporation_id()));
        return assetListDTOList;
    }

    /**
     * 军团资产所在地点
     * */
    @Override
    public List<EvsiAssetLocationDTO> assetCorpLocations() {
        EvsiCharacterPublicInfoDTO characters = characterInterceptor.getCharacters(null);
        List<BigInteger> itemId = this.assetCorpList().stream().map(EvsiAssetListDTO::getItem_id).collect(Collectors.toList());
        return assetsClient.assetCorpLocations(characters.getCorporation_id(), itemId);
    }

    /**
     * 查询军团资产名称
     * */
    @Override
    public List<EvsiAssetNameDTO> assetCorpNames() {
        EvsiCharacterPublicInfoDTO characters = characterInterceptor.getCharacters(null);
        List<BigInteger> itemId = this.assetCorpList().stream().map(EvsiAssetListDTO::getItem_id).collect(Collectors.toList());
        return assetsClient.assetCorpNames(characters.getCorporation_id(), itemId);
    }

    /**
     * 查询当前资产信息，并产生价格
     * */
    @Override
    public Map<String,Object> assetsOnMarket(BigInteger locationId, Integer type, Integer state) {

        List<JSONObject> marketStat = new ArrayList<>();
        List<EvsiAssetsOnMarketVO> assetsOnMarketVOList = new ArrayList<>();
        Map<String,Object> assetsOnMarketMap = new LinkedHashMap<>(); //用linkedHashMao保证存储顺序一致

        // 配置防止科学计数
        NumberFormat instance = NumberFormat.getInstance();
        instance.setGroupingUsed(false);

        // 获取资产数据 0:个人资产， 1:军团资产
        List<EvsiAssetListDTO> assetList = new ArrayList<>();
        if (state == 0) {
            assetList = this.assetList();
        } else if (state == 1) {
            assetList = this.assetCorpList();
        }

        // 获取当前某个地点的资产
        if (locationId != null) {
            assetList = assetList.stream().filter(v -> Objects.equals(v.getLocation_id(), locationId)).collect(Collectors.toList());
        }

        // 通过assets资产信息获取到物品信息
        assetList.forEach(v -> {
            EvsiInvtypes invtypes = invtypesService.getOne(new LambdaQueryWrapper<EvsiInvtypes>().eq(EvsiInvtypes::getTypeId, v.getType_id()));
            if (ObjectUtil.isNull(invtypes)) {
                // 如果invtypes为空，则再数据库中不存在，需要进行数据库更新
                return;
            }
            assetsOnMarketVOList.add(EvsiAssetsOnMarketVO.builder()
                    .typeId(v.getType_id())
                    .typeName(invtypes.getTypeName())
                    .quantity(v.getQuantity())
                    .locationId(v.getLocation_id())
                    .packagedVolume(invtypes.getPackagedVolume())
                    .volume(invtypes.getVolume())
                    .build());
        });

        // 获取资产的type_id,并将type_id分片，用来查询价格
        List<Integer> collect = assetsOnMarketVOList.stream().map(EvsiAssetsOnMarketVO::getTypeId).collect(Collectors.toList());
        List<List<Integer>> partition = ListUtil.partition(collect, 200);
        partition.forEach(v -> {
            String join = CollUtil.join(v, ",");
            List<JSONObject> market = thirdClient.marketstat(join, "10000002");
            marketStat.addAll(market);
        });

        // 将价格赋值给资产list并进行数据和以及税务比例换算
        marketStat.forEach(item -> {
            EvsiMarketStatDTO evsiMarketStatDTO = JSON.toJavaObject(item, EvsiMarketStatDTO.class);
            assetsOnMarketVOList.forEach(v -> {
                if (ObjectUtil.equal(v.getTypeId(), evsiMarketStatDTO.getBuy().getForQuery().getTypes().get(0))) {
                    v.setSellMin(Double.valueOf(instance.format(evsiMarketStatDTO.getSell().getMin() * v.getQuantity())));
                    v.setSellMedian(Double.valueOf(instance.format(evsiMarketStatDTO.getSell().getMedian() * v.getQuantity())));
                    v.setSellTax(Double.valueOf(instance.format((evsiMarketStatDTO.getSell().getMin() - evsiMarketStatDTO.getSell().getMin() * sellTaxValue) * v.getQuantity())));

                    v.setBuyMax(Double.valueOf(instance.format(evsiMarketStatDTO.getBuy().getMax() * v.getQuantity())));
                    v.setBuyMedian(Double.valueOf(instance.format(evsiMarketStatDTO.getBuy().getMedian() * v.getQuantity())));
                    v.setBuyTax(Double.valueOf(instance.format((evsiMarketStatDTO.getBuy().getMax() - evsiMarketStatDTO.getBuy().getMax() * buyTaxValue) * v.getQuantity())));
                }
            });
        });

        // 根据状态进行数据排序
        List<EvsiAssetsOnMarketVO> assetsOnMarketVOs = new ArrayList<>();
        if (type == null) {
            type = 0;
        }
        switch (type) {
            case 0:
                assetsOnMarketVOs = assetsOnMarketVOList;
            case 1:
                assetsOnMarketVOs = assetsOnMarketVOList.stream().sorted(Comparator.comparing(EvsiAssetsOnMarketVO::getSellMin)).collect(Collectors.toList());
            case 2:
                assetsOnMarketVOs = assetsOnMarketVOList.stream().sorted(Comparator.comparing(EvsiAssetsOnMarketVO::getSellMin).reversed()).collect(Collectors.toList());
            case 3:
                assetsOnMarketVOs = assetsOnMarketVOList.stream().sorted(Comparator.comparing(EvsiAssetsOnMarketVO::getBuyMax)).collect(Collectors.toList());
            case 4:
                assetsOnMarketVOs = assetsOnMarketVOList.stream().sorted(Comparator.comparing(EvsiAssetsOnMarketVO::getBuyMax).reversed()).collect(Collectors.toList());
        }

        Double sellMin = assetsOnMarketVOList.stream().map(EvsiAssetsOnMarketVO::getSellMin).reduce(Double::sum).get();
        Double sellTax = assetsOnMarketVOList.stream().map(EvsiAssetsOnMarketVO::getSellTax).reduce(Double::sum).get();
        Double buyMax = assetsOnMarketVOList.stream().map(EvsiAssetsOnMarketVO::getBuyMax).reduce(Double::sum).get();
        Double buyTax = assetsOnMarketVOList.stream().map(EvsiAssetsOnMarketVO::getBuyTax).reduce(Double::sum).get();

        assetsOnMarketMap.put("sell", instance.format(sellMin));
        assetsOnMarketMap.put("buy", instance.format(buyMax));
        assetsOnMarketMap.put("sellTax", instance.format(sellTax));
        assetsOnMarketMap.put("buyTax", instance.format(buyTax));
        assetsOnMarketMap.put("list", assetsOnMarketVOs);
        return assetsOnMarketMap;
    }
}
